using Collections = System.Collections.Generic;
using IO = System.IO;
using Text = System.Text;
using System;

namespace NU.Separacion{
public sealed class Separador
{
	private readonly Collections.IList<object> resultado;

    public Separador(String archivo)
	{
		using (IO.TextReader input = IO.File.OpenText(archivo))
		{
			this.resultado = new Collections.List<object>();
			this.Escanear(input);
		}
	}

	public Collections.IList<object> Muestras
	{
		get { return this.resultado; }
	}

    #region ArithmiticConstants

    /*/ Constants to represent arithmitic tokens. This could
    // be alternatively written as an enum.
    public static readonly object Suma = new object();
    public static readonly object Resta = new object();
    public static readonly object Multiplicacion = new object();
    public static readonly object Division = new object();
	public static readonly object Coma = new object();
    public static readonly object PutoYComa = new object();
    public static readonly object Igual = new object();
	public static readonly object Asignacion = new object();
	public static readonly object ParentesisIzquierdo = new object();
	public static readonly object ParentesisDerecho = new object();
	public static readonly object LlaveIzquierdo = new object();
	public static readonly object LlaveDerecho = new object();
	public static readonly object CorcheteIzquierdo = new object ();
	public static readonly object CorcheteDerecho = new object ();
		*/
    #endregion

	private void Escanear(IO.TextReader input)
	{
		while (input.Peek() != -1)
		{
			char ch = (char)input.Peek();

            // Scan individual tokens
			if (char.IsWhiteSpace(ch))
			{
				// eat the current char and skip ahead!
				input.Read();
			}
			else if (char.IsLetter(ch) || ch == '_')
			{
				// keyword or identifier

				Text.StringBuilder accum = new Text.StringBuilder();

				while (char.IsLetterOrDigit(ch) || ch == '_')
				{
					accum.Append(ch);
					input.Read();

					if (input.Peek() == -1)
					{
						break;
					}
					else
					{
						ch = (char)input.Peek();
					}
				}

				this.resultado.Add(accum.ToString());
			}
            else if (ch == '"' || ch == '\'')
			{
				char comilla = ch;
				// string literal
				Text.StringBuilder accum = new Text.StringBuilder();

				input.Read(); // skip the '"'

                if (input.Peek() == -1)
				{
					throw new System.Exception("unterminated string literal");
				}

				while ((ch = (char)input.Peek()) != comilla)
				{
					accum.Append(ch);
					input.Read();

					if (input.Peek() == -1)
					{
						throw new System.Exception("unterminated string literal");
					}
				}

				// skip the terminating "
				input.Read();
				this.resultado.Add(accum);
			}
			else if (char.IsDigit(ch))
			{
				// numeric literal
				Text.StringBuilder accum = new Text.StringBuilder();

				while (char.IsDigit(ch))
				{
					accum.Append(ch);
					input.Read();

					if (input.Peek() == -1)
					{
						break;
					}
					else
					{
						ch = (char)input.Peek();
					}
				}

				this.resultado.Add(int.Parse(accum.ToString()));
			}
			else switch (ch)
			{
				case '+':
					input.Read();
					this.resultado.Add(Operador.Suma);
					break;

				case '-':
					input.Read();
					this.resultado.Add(Operador.Resta);
					break;

				case '*':
					input.Read();
					this.resultado.Add(Operador.Multiplicacion);
					break;

				case '/':
					input.Read();
					this.resultado.Add(Operador.Division);
					break;

				case '=':
					input.Read();
					this.resultado.Add(Operador.Igual);
					break;

				case ';':
					input.Read();
					this.resultado.Add(Operador.PutoYComa);
					break;

				case '(':
					input.Read();
					this.resultado.Add(Operador.ParentesisIzquierdo);
					break;

				case ')':
					input.Read();
					this.resultado.Add(Operador.ParentesisDerecho);
					break;

				case '{':
					input.Read();
					this.resultado.Add(Operador.LlaveIzquierdo);
					break;

				case '}':
					input.Read();
					this.resultado.Add(Operador.LlaveDerecho);
					break;

				case '#':
					input.Read();
					while(input.Peek() != -1 && (ch = (char)input.Peek()) !=  '\n')
						input.Read();	
					break;

				default:
					throw new System.Exception("Scanner encountered unrecognized character '" + ch + "'");
			}

        }
    }
}
}